local Networking = Tubes.Networking
local NetMessage = {}
NetMessage.__index = NetMessage

Networking.NetMessageReader = Tubes.MakeConstructor (NetMessage)

local PlayerBuffer = {}
concommand.Add ("tubes_transfer", function (ply, _, args)
	PlayerBuffer [ply] = (PlayerBuffer [ply] and PlayerBuffer [ply] or "") .. args [1]
end)

concommand.Add ("tubes_transfer_end", function (ply, _, args)
	local Name = Tubes.Networking.StringPool:LookupString (tonumber (args [1]))
	ErrorNoHalt ("Received umsg " .. Name .. "\n")
	if Networking.Readers [Name] then
		Networking.Readers [Name] (Networking.NetMessageReader (ply, PlayerBuffer [ply]))
	else
		
	end
	PlayerBuffer [ply] = ""
end)

Tubes:AddEventListener ("PlayerConnected", function (ply, isLocalPlayer)
	PlayerBuffer [ply] = ""
end)

Tubes:AddEventListener ("PlayerDisconnected", function (ply)
	PlayerBuffer [ply] = nil
end)

function NetMessage:ctor (source, buffer)
	self.Source = source
	self.Buffer = buffer
	self.Index = 1
end

function NetMessage:BitField ()
	local Bits = {false, false, false, false, false, false, false, false}
	local UChar = self:UChar ()
	local Weight = 128
	for i = 1, 8 do
		if UChar >= Weight then
			Bits [9 - i] = true
			UChar = UChar - Weight
		end
		Weight = Weight / 2
	end
	return unpack (Bits)
end

function NetMessage:Char ()
	return self:UChar () - 128
end

function NetMessage:GetSource ()
	return self.Source
end

function NetMessage:Player ()
	return ents.GetByIndex (self:UChar ())
end

function NetMessage:Short ()
	return self:UShort () - 32768
end

function NetMessage:String ()
	if self.Buffer:sub (self.Index, self.Index) == "\2" then
		self.Index = self.Index + 1
		return ""
	end
	local End = self.Buffer:find ("[^\1]\2", self.Index)
	local String = self.Buffer:sub (self.Index, End)
	self.Index = End + 2
	return String
end

function NetMessage:UChar ()
	local Byte = string.byte (self.Buffer:sub (self.Index, self.Index))
	self.Index = self.Index + 1
	if Byte ~= 255 then
		return Byte
	end
	Byte = Networking.BadCharsLookup [self.Buffer:sub (self.Index, self.Index)]
	
	self.Index = self.Index + 1
	return Byte
end

function NetMessage:UShort ()
	local Weight = 1
	local Short = 0
	
	local Byte = string.byte (self.Buffer:sub (self.Index, self.Index))
	self.Index = self.Index + 1
	Short = Short + (Byte & 63) * Weight
	if Byte < 192 then
		Weight = Weight * 64
		Byte = string.byte (self.Buffer:sub (self.Index, self.Index))
		self.Index = self.Index + 1
		Short = Short + (Byte & 63) * Weight
		if Byte < 192 then
			Weight = Weight * 64
			Byte = string.byte (self.Buffer:sub (self.Index, self.Index))
			self.Index = self.Index + 1
			Short = Short + (Byte & 63) * Weight
		end
	end
	return Short
end